home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
general
/
viewers
/
prev
/
prev.lha
/
gram.y
< prev
next >
Wrap
Text File
|
1991-03-12
|
22KB
|
1,163 lines
/*
* parser for the input language to art
*/
%{
#include <stdio.h>
#include <math.h>
#include "art.h"
#include "macro.h"
extern object *objectinit(),
*compinit(),
*csginit(),
*getcsgobj(),
*getcsgexp();
extern symbol *lookup();
extern light *lightinit();
extern attr *astackp;
extern mats *mstackp;
extern object *oblist;
extern light *lights;
extern vector eye, viewup, ref;
extern int lookatdone;
extern matrix trans;
extern float fov;
extern float near;
extern char *title;
extern int maxhitlevel, raysperpix, pixelgrid;
extern long filetype;
extern colour backcol;
extern float fogfactor, rfactor;
extern colour hazecolour;
extern float sourceradius;
extern float falloff;
extern float ri;
extern float twist;
extern float screenx, screeny;
extern int orthographic;
extern float eval_fexpr();
extern int eval_iexpr();
extern expression *get_expr(), *get_varexpr();
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
static int objdefined = FALSE;
extern symbol **ostackp;
%}
%union{
object *y_obj;
light *y_lht;
vector *y_pnt;
details *y_det;
char *y_str;
eqn *y_eqn;
term *y_trm;
expression *y_exp;
symbol *y_sym;
csgnode *y_csg;
float y_flt;
int y_int;
};
%token CSG
%token COMPOSITE
%token <y_sym> OBJECT_TYPE
%token <y_flt> FLOAT
%token <y_int> INTEGER FILETYPE OPTION
%token <y_str> NAME
%type <y_exp> expr
%type <y_trm> termlist term
%type <y_csg> csgexpr
%type <y_det> csgbody object definition vbody vitem
%type <y_det> body bodyitem
%type <y_det> transform stlist compbody wbody witem mbody mitem
%token LBRACE RBRACE LP RP RADIUS RADII COLOUR CENTER VERTEX COMMA PCENT
%token MATERIAL REFI MINUS AMBIENT LIGHT INTENSITY LOCATION NAME DOLS
%token EQUATION TILE OFFFILE BASE TOP CONST COEFFS ART_SCALE ART_ROTATE
%token ART_TRANSLATE PROJECTION ORTHOGRAPHIC PERSPECTIVE
%token TITLE REFLECTANCE DOT ON OFF LOOKAT FIELDOFVIEW TRANSPARENCY
%token RAYSPERPIXEL BACKGROUND SIZE MAXHITLEVEL OUTPUT FILETYPE ORDER
%token ABSORPTION VREF1 VREF2 NUMRAYS OBJECT TEXTURE DIRECTION ANGLE UP
%token TWENTYFIVEBIT RANGE MAP BLENDCOLOR SCALEFACTORS VORTFILE HAZECOLOUR
%token FOGFACTOR RFACTOR FALLOFF QUOTE REPEAT SHADOWS COLOURFILE VNORMALFILE
%token SCALEFACTOR SOURCE AMPLITUDE WAVELENGTH PHASE TURBULENCE SQUEEZE
%token DAMPING SOURCERADIUS NORMAL COMPLEXVERTEX SCREENSIZE MAXTREEDEPTH
%token BLEND COLOURMAP MAPVALUES PIXELGRID RI COLOURBLEND NORMALFILE
%token BEAMDISTRIBUTION INSIDEANGLE
%left PLUS MINUS
%left MULT DIV
%left POWER
%left UMINUS
%right EQUALS
%%
input : /* NULL */
{
objdefined = FALSE;
}
| input hitem
| input light
| input object
{
object *obj, *head;
if ((head = objectinit($2->u.obj.sym, $2->u.obj.det)) != (object *)NULL) {
for (obj = head; obj->nxt != (object *)NULL; obj = obj->nxt)
;
obj->nxt = oblist;
oblist = head;
}
objdefined = TRUE;
free($2);
}
| input statement
| input definition
{
objdefined = TRUE;
free($2);
}
;
hitem : TITLE NAME
| FIELDOFVIEW expr
{
float val;
val = eval_fexpr($2);
if (val == 0.0 || val == 360.0)
fatal("art: idiotic angle in field of view.\n");
near = 1.0 / tan(M_PI / 360.0 * val);
fov = val;
}
| SCREENSIZE expr COMMA expr
{
screenx = eval_fexpr($2) / 2.0;
screeny = eval_fexpr($4) / 2.0;
}
| MAXTREEDEPTH expr
| RAYSPERPIXEL expr
| HAZECOLOUR expr COMMA expr COMMA expr
| FOGFACTOR expr
| RFACTOR expr
| SOURCERADIUS expr
| PROJECTION PERSPECTIVE
{
orthographic = FALSE;
}
| PROJECTION ORTHOGRAPHIC
{
orthographic = TRUE;
}
| PIXELGRID ON
| TWENTYFIVEBIT ON
| TWENTYFIVEBIT OFF
| UP LP expr COMMA expr COMMA expr RP
{
viewup.x = eval_fexpr($3);
viewup.y = eval_fexpr($5);
viewup.z = eval_fexpr($7);
}
| LOOKAT LP expr COMMA expr COMMA expr COMMA expr COMMA expr COMMA expr COMMA expr RP
{
vector t, u, s;
matrix m, tmp;
double val, vy, vz, sinval, cosval;
twist = -eval_fexpr($15);
eye.x = eval_fexpr($3);
eye.y = eval_fexpr($5);
eye.z = eval_fexpr($7);
ref.x = eval_fexpr($9);
ref.y = eval_fexpr($11);
ref.z = eval_fexpr($13);
fprintf(stderr, "eye: %f %f %f\n", eye.x, eye.y, eye.z);
fprintf(stderr, "ref: %f %f %f\n", ref.x, ref.y, ref.z);
fprintf(stderr, "twist: %f\n", twist);
fprintf(stderr, "fov: %f\n", fov);
}
| BACKGROUND expr COMMA expr COMMA expr
| MAXHITLEVEL expr
| OUTPUT FILETYPE
| FALLOFF expr
| RI expr
| SHADOWS OFF
;
light : LIGHT LBRACE lbody RBRACE
;
lbody : /* NULL */
| lbody litem
;
litem : LOCATION LP expr COMMA expr COMMA expr RP
| RADIUS expr
| NUMRAYS expr
| INSIDEANGLE expr
| BEAMDISTRIBUTION expr
| ANGLE expr
| DIRECTION LP expr COMMA expr COMMA expr RP
| COLOUR expr COMMA expr COMMA expr
| SHADOWS OFF
;
object : OBJECT_TYPE LBRACE body RBRACE
{
$$ = (details *)smalloc(sizeof(details));
$$->type = OBJECT;
$$->u.obj.sym = $1;
$$->u.obj.det = $3;
$$->nxt = (details *)NULL;
}
| OBJECT_TYPE
{
$$ = (details *)smalloc(sizeof(details));
$$->type = OBJECT;
$$->u.obj.sym = $1;
$$->u.obj.det = (details *)NULL;
$$->nxt = (details *)NULL;
}
| COMPOSITE LBRACE compbody RBRACE
{
$$ = (details *)smalloc(sizeof(details));
$$->type = COMP_OBJ;
$$->u.obj.sym = (symbol *)NULL;
$$->u.obj.det = $3;
$$->nxt = (details *)NULL;
}
| CSG LBRACE
{
ostackp++;
*ostackp = (symbol *)NULL;
}
csgbody csgexpr RBRACE
{
details *d;
symbol *s;
ostackp--;
d = (details *)smalloc(sizeof(details));
d->type = $4->type;
d->u.csgobj.tree = $5;
d->u.csgobj.det = $4;
d->nxt = (details *)NULL;
s = (symbol *)smalloc(sizeof(symbol));
s->type = CSG_OBJ;
s->u.det = d;
$$ = (details *)smalloc(sizeof(details));
$$->type = OBJECT;
$$->u.obj.sym = s;
$$->u.obj.det = (details *)NULL;
$$->nxt = (details *)NULL;
}
;
compbody: /* NULL */
{
$$ = (details *)NULL;
}
| compbody transform
{
$$ = $2;
$2->nxt = $1;
}
| compbody bodyitem
{
$$ = $2;
$2->nxt = $1;
}
| compbody object
{
$$ = $2;
$2->nxt = $1;
}
;
statement: NAME EQUALS expr
{
defvar($1, $3);
}
| transform
{
switch ($1->type) {
case ART_TRANSLATE:
translate($1->u.v.x, $1->u.v.y, $1->u.v.z);
break;
case ART_SCALE:
scale($1->u.v.x, $1->u.v.y, $1->u.v.z);
break;
case ART_ROTATE:
rotate($1->u.rot.ang, $1->u.rot.axis);
break;
default:
fatal("art: bad transform type in switch.\n");
}
free($1);
}
| bodyitem
{
surface *s;
/*
* don't want to change someone else's
* material properties
*/
if (objdefined) {
s = (surface *)smalloc(sizeof(surface));
*s = *astackp->s;
astackp->s = s;
} else
s = astackp->s;
switch ($1->type) {
case COLOUR:
s->c.r = $1->u.c.r;
s->c.g = $1->u.c.g;
s->c.b = $1->u.c.b;
break;
case AMBIENT:
s->a.r = $1->u.c.r;
s->a.g = $1->u.c.g;
s->a.b = $1->u.c.b;
break;
case TEXTURE:
break;
case MATERIAL:
s->ri = $1->u.mat.ri;
s->kd = $1->u.mat.kd;
s->ks = $1->u.mat.ks;
s->ksexp = $1->u.mat.ksexp;
break;
case REFLECTANCE:
s->refl = $1->u.f;
break;
case TRANSPARENCY:
s->trans = $1->u.f;
break;
case ABSORPTION:
s->falloff = $1->u.f;
break;
case ON:
astackp->options |= $1->u.i;
break;
case OFF:
astackp->options &= ~$1->u.i;
break;
default:
fatal("art: bad statement type in switch.\n");
}
free($1);
}
| REPEAT expr LBRACE stlist RBRACE
{
dorepeat($2, $4);
}
;
stlist : /* NULL */
{
$$ = (details *)NULL;
}
| stlist transform
{
$2->nxt = $1;
$$ = $2;
}
| stlist OBJECT_TYPE
{
$$ = (details *)smalloc(sizeof(details));
$$->type = OBJECT;
$$->u.sym = $2;
$$->nxt = $1;
}
| stlist REPEAT expr LBRACE stlist RBRACE
{
$$ = (details *)smalloc(sizeof(details));
$$->type = REPEAT;
$$->u.rpt.expr = $3;
$$->u.rpt.stmt = $5;
$$->nxt = $1;
}
;
body : /* NULL */
{
$$ = (details *)NULL;
}
| body transform
{
$2->nxt = $1;
$$ = $2;
}
| body bodyitem
{
$2->nxt = $1;
$$ = $2;
}
;
bodyitem: CENTER LP expr COMMA expr COMMA expr RP
{
$$ = (details *)smalloc(sizeof(details));
$$->type = CENTER;
$$->u.v.x = eval_fexpr($3);
$$->u.v.y = eval_fexpr($5);
$$->u.v.z = eval_fexpr($7);
$$->nxt = (details *)NULL;
}
| ORDER expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = ORDER;
$$->u.i = eval_iexpr($2);
$$->nxt = (details *)NULL;
}
| RADIUS expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = RADIUS;
$$->u.f = eval_fexpr($2);
$$->nxt = (details *)NULL;
}
| RADII expr COMMA expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = RADII;
$$->u.v.x = eval_fexpr($2);
$$->u.v.y = eval_fexpr($4);
$$->nxt = (details *)NULL;
}
| RADII expr COMMA expr COMMA expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = RADII;
$$->u.v.x = eval_fexpr($2);
$$->u.v.y = eval_fexpr($4);
$$->u.v.z = eval_fexpr($6);
$$->nxt = (details *)NULL;
}
| VERTEX vbody
{
if ($2->nxt == (details *)NULL) {
$2->type = VERTEX;
$$ = $2;
} else {
$$ = (details *)smalloc(sizeof(details));
$$->type = COMPLEXVERTEX;
$$->u.det = $2;
$$->nxt = (details *)NULL;
}
}
| EQUATION DOLS termlist EQUALS expr DOLS
{
$$ = (details *)smalloc(sizeof(details));
$$->type = EQUATION;
$$->u.t = (term *)smalloc(sizeof(term));
$$->u.t->coef = -eval_fexpr($5);
$$->u.t->xp = 0;
$$->u.t->yp = 0;
$$->u.t->zp = 0;
$$->u.t->nxt = $3;
$$->nxt = (details *)NULL;
}
| COEFFS expr COMMA expr COMMA expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = COEFFS;
$$->u.v.x = eval_fexpr($2);
$$->u.v.y = eval_fexpr($4);
$$->u.v.z = eval_fexpr($6);
$$->nxt = (details *)NULL;
}
| CONST expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = CONST;
$$->u.f = eval_fexpr($2);
$$->nxt = (details *)NULL;
}
| TOP expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = TOP;
$$->u.f = eval_fexpr($2);
$$->nxt = (details *)NULL;
}
| BASE expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = BASE;
$$->u.f = eval_fexpr($2);
$$->nxt = (details *)NULL;
}
| OFFFILE NAME
{
$$ = (details *)smalloc(sizeof(details));
$$->type = OFFFILE;
$$->u.s = $2;
$$->nxt = (details *)NULL;
}
| COLOURFILE NAME
{
$$ = (details *)smalloc(sizeof(details));
$$->type = COLOURFILE;
$$->u.s = $2;
$$->nxt = (details *)NULL;
}
| VNORMALFILE NAME
{
$$ = (details *)smalloc(sizeof(details));
$$->type = VNORMALFILE;
$$->u.s = $2;
$$->nxt = (details *)NULL;
}
| NORMALFILE NAME
{
$$ = (details *)smalloc(sizeof(details));
$$->type = NORMALFILE;
$$->u.s = $2;
$$->nxt = (details *)NULL;
}
| COLOUR expr COMMA expr COMMA expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = COLOUR;
$$->u.c.r = eval_fexpr($2);
$$->u.c.g = eval_fexpr($4);
$$->u.c.b = eval_fexpr($6);
$$->nxt = (details *)NULL;
}
| MATERIAL expr COMMA expr COMMA expr COMMA expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = MATERIAL;
$$->u.mat.ri = eval_fexpr($2);
$$->u.mat.kd = eval_fexpr($4);
$$->u.mat.ks = eval_fexpr($6);
$$->u.mat.ksexp = eval_iexpr($8);
$$->nxt = (details *)NULL;
}
| AMBIENT expr COMMA expr COMMA expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = AMBIENT;
$$->u.v.x = eval_fexpr($2);
$$->u.v.y = eval_fexpr($4);
$$->u.v.z = eval_fexpr($6);
$$->nxt = (details *)NULL;
}
| REFLECTANCE expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = REFLECTANCE;
$$->u.f = eval_fexpr($2);
$$->nxt = (details *)NULL;
}
| TRANSPARENCY expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = TRANSPARENCY;
$$->u.f = eval_fexpr($2);
$$->nxt = (details *)NULL;
}
| ABSORPTION expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = ABSORPTION;
$$->u.f = eval_fexpr($2);
$$->nxt = (details *)NULL;
}
| OPTION ON
{
$$ = (details *)smalloc(sizeof(details));
$$->type = ON;
$$->u.i = $1;
$$->nxt = (details *)NULL;
}
| OPTION OFF
{
$$ = (details *)smalloc(sizeof(details));
$$->type = OFF;
$$->u.i = $1;
$$->nxt = (details *)NULL;
}
| TEXTURE NAME LBRACE texture_ops RBRACE
{
$$ = (details *)smalloc(sizeof(details));
$$->type = TEXTURE;
$$->nxt = (details *)NULL;
}
| TEXTURE NAME textitem
{
$$ = (details *)smalloc(sizeof(details));
$$->type = TEXTURE;
$$->nxt = (details *)NULL;
}
| TEXTURE TILE textitem
{
$$ = (details *)smalloc(sizeof(details));
$$->type = TEXTURE;
$$->nxt = (details *)NULL;
}
| TEXTURE TILE LBRACE texture_ops RBRACE
{
$$ = (details *)smalloc(sizeof(details));
$$->type = TEXTURE;
$$->nxt = (details *)NULL;
}
| TILE NAME SIZE expr COMMA expr
{
details *d1, *d2;
d1 = (details *)smalloc(sizeof(details));
d1->type = VORTFILE;
d1->u.s = $2;
d2 = (details *)smalloc(sizeof(details));
d2->type = SIZE;
d2->u.v.x = eval_fexpr($4);
d2->u.v.y = eval_fexpr($6);
d1->nxt = d2;
d2->nxt = (details *)NULL;
$$ = (details *)smalloc(sizeof(details));
$$->type = TEXTURE;
$$->nxt = (details *)NULL;
}
;
vbody : vitem
{
$$ = $1;
}
| vbody COMMA vitem
{
$3->nxt = $1;
$$ = $3;
}
;
vitem : LP expr COMMA expr COMMA expr RP
{
$$ = (details *)smalloc(sizeof(details));
$$->type = VERTEX;
$$->u.v.x = eval_fexpr($2);
$$->u.v.y = eval_fexpr($4);
$$->u.v.z = eval_fexpr($6);
$$->nxt = (details *)NULL;
}
| expr COMMA expr COMMA expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = COLOUR;
$$->u.v.x = eval_fexpr($1);
$$->u.v.y = eval_fexpr($3);
$$->u.v.z = eval_fexpr($5);
$$->nxt = (details *)NULL;
}
transform: ART_ROTATE LP expr COMMA expr RP
{
$$ = (details *)smalloc(sizeof(details));
$$->type = ART_ROTATE;
$$->u.rot.ang = eval_fexpr($3);
$$->u.rot.axis = eval_iexpr($5);
$$->nxt = (details *)NULL;
}
| ART_TRANSLATE LP expr COMMA expr COMMA expr RP
{
$$ = (details *)smalloc(sizeof(details));
$$->type = ART_TRANSLATE;
$$->u.v.x = eval_fexpr($3);
$$->u.v.y = eval_fexpr($5);
$$->u.v.z = eval_fexpr($7);
$$->nxt = (details *)NULL;
}
| ART_SCALE LP expr COMMA expr COMMA expr RP
{
$$ = (details *)smalloc(sizeof(details));
$$->type = ART_SCALE;
$$->u.v.x = eval_fexpr($3);
$$->u.v.y = eval_fexpr($5);
$$->u.v.z = eval_fexpr($7);
$$->nxt = (details *)NULL;
}
;
texture_ops: /* NULL */
| texture_ops textitem
| texture_ops transform
;
textitem: MAP NAME
| COLOURMAP LBRACE mbody RBRACE
| BLEND expr
| RANGE expr
| BLENDCOLOR expr COMMA expr COMMA expr
| SIZE expr COMMA expr
| SCALEFACTORS expr COMMA expr COMMA expr
| SCALEFACTOR expr
| VORTFILE NAME
| TURBULENCE expr
| SQUEEZE expr
| SOURCE LBRACE wbody RBRACE
;
mbody : mitem
{
$$ = (details *)NULL;
}
| mbody COMMA mitem
{
$3->nxt = $1;
$$ = $3;
}
;
mitem : expr COMMA expr COMMA expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = MAPVALUES;
$$->u.v.x = eval_fexpr($1);
$$->u.v.y = eval_fexpr($3);
$$->u.v.z = eval_fexpr($5);
$$->nxt = (details *)NULL;
}
;
wbody : /* NULL */
{
$$ = (details *)NULL;
}
| wbody witem
{
$2->nxt = $1;
$$ = $2;
}
;
witem : CENTER LP expr COMMA expr COMMA expr RP
{
$$ = (details *)smalloc(sizeof(details));
$$->type = CENTER;
$$->u.v.x = eval_fexpr($3);
$$->u.v.y = eval_fexpr($5);
$$->u.v.z = eval_fexpr($7);
$$->nxt = (details *)NULL;
}
| WAVELENGTH expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = WAVELENGTH;
$$->u.f = eval_fexpr($2);
$$->nxt = (details *)NULL;
}
| AMPLITUDE expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = AMPLITUDE;
$$->u.f = eval_fexpr($2);
$$->nxt = (details *)NULL;
}
| PHASE expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = PHASE;
$$->u.f = eval_fexpr($2);
$$->nxt = (details *)NULL;
}
| DAMPING expr
{
$$ = (details *)smalloc(sizeof(details));
$$->type = DAMPING;
$$->u.f = eval_fexpr($2);
$$->nxt = (details *)NULL;
}
;
csgbody : /* NULL */
{
$$ = (details *)NULL;
}
| csgbody bodyitem
{
$2->nxt = $1;
$$ = $2;
}
| csgbody transform
{
$2->nxt = $1;
$$ = $2;
}
| csgbody definition
{
$2->nxt = $1;
$$ = $2;
}
;
definition: OBJECT_TYPE NAME LBRACE body RBRACE
{
defobj($2, $1->type, $4);
$$ = (details *)smalloc(sizeof(details));
$$->type = OBJECT;
$$->u.sym = lookup($2);
$$->nxt = (details *)NULL;
}
| CSG NAME LBRACE
{
ostackp++;
*ostackp = (symbol *)NULL;
}
csgbody csgexpr RBRACE
{
details *d;
ostackp--;
d = (details *)smalloc(sizeof(details));
d->type = $6->type;
d->u.csgobj.tree = $6;
d->u.csgobj.det = $5;
d->nxt = (details *)NULL;
defobj($2, CSG_OBJ, d);
$$ = (details *)smalloc(sizeof(details));
$$->type = OBJECT;
$$->u.sym = lookup($2);
$$->nxt = (details *)NULL;
}
| COMPOSITE NAME LBRACE compbody RBRACE
{
defobj($2, COMP_OBJ, $4);
$$ = (details *)smalloc(sizeof(details));
$$->type = OBJECT;
$$->u.sym = lookup($2);
$$->nxt = (details *)NULL;
}
;
csgexpr : OBJECT_TYPE
{
$$ = (csgnode *)smalloc(sizeof(csgnode));
$$->type = OBJECT;
$$->u.sym = $1;
}
| csgexpr PLUS csgexpr
{
$$ = (csgnode *)smalloc(sizeof(csgnode));
$$->type = CSG_ADD;
$$->u.branch.left = $1;
$$->u.branch.right = $3;
}
| csgexpr MULT csgexpr
{
$$ = (csgnode *)smalloc(sizeof(csgnode));
$$->type = CSG_INT;
$$->u.branch.left = $1;
$$->u.branch.right = $3;
}
| csgexpr MINUS csgexpr
{
$$ = (csgnode *)smalloc(sizeof(csgnode));
$$->type = CSG_SUB;
$$->u.branch.left = $1;
$$->u.branch.right = $3;
}
| LP csgexpr RP
{
$$ = $2;
}
| NAME
{
char buf[BUFSIZ];
sprintf(buf, "art: object %s not defined.\n", $1);
fatal(buf);
}
;
termlist: term
{
$$ = $1;
}
| termlist termlist %prec MULT
{
term *t, *p, *np, *prod;
prod = (term *)NULL;
for (p = $1; p != (term *)NULL; p = p->nxt) {
for (np = $2; np != (term *)NULL; np = np->nxt) {
t = (term *)smalloc(sizeof(term));
*t = *np;
t->coef *= p->coef;
t->xp += p->xp;
t->yp += p->yp;
t->zp += p->zp;
t->nxt = prod;
prod = t;
}
}
for (t = $1; t != (term *)NULL; t = np) {
np = t->nxt;
free(t);
}
for (t = $2; t != (term *)NULL; t = np) {
np = t->nxt;
free(t);
}
$$ = prod;
}
| LP termlist RP
{
$$ = $2;
}
| LP termlist RP POWER LBRACE INTEGER RBRACE
{
term *t, *p, *np, *prod, *nprod;
int i;
prod = $2;
for (i = 1; i != $6; i++) {
nprod = (term *)NULL;
for (p = $2; p != (term *)NULL; p = p->nxt) {
for (np = prod; np != (term *)NULL; np = np->nxt) {
t = (term *)smalloc(sizeof(term));
*t = *np;
t->coef *= p->coef;
t->xp += p->xp;
t->yp += p->yp;
t->zp += p->zp;
t->nxt = nprod;
nprod = t;
}
}
if (prod != $2)
for (t = prod; t != (term *)NULL; t = np) {
np = t->nxt;
free(t);
}
prod = nprod;
}
for (t = $2; t != (term *)NULL; t = np) {
np = t->nxt;
free(t);
}
$$ = prod;
}
| termlist PLUS termlist
{
term *p;
for (p = $3; p->nxt != (term *)NULL; p = p->nxt)
;
$$ = $3;
p->nxt = $1;
}
| termlist MINUS termlist
{
term *p, *lp;
for (p = $3; p != (term *)NULL; p = p->nxt) {
p->coef *= -1.0;
lp = p;
}
$$ = $3;
lp->nxt = $1;
}
;
term : NAME
{
char *p;
$$ = (term *)smalloc(sizeof(term));
$$->coef = 1;
$$->xp = 0;
$$->yp = 0;
$$->zp = 0;
$$->nxt = (term *)NULL;
for (p = $1; *p != 0; p++)
switch (*p) {
case 'x':
$$->xp += 1;
break;
case 'y':
$$->yp += 1;
break;
case 'z':
$$->zp += 1;
break;
default:
fatal("art: illegal name in equation.\n");
}
}
| FLOAT
{
$$ = (term *)smalloc(sizeof(term));
$$->coef = $1;
$$->xp = 0;
$$->yp = 0;
$$->zp = 0;
$$->nxt = (term *)NULL;
}
| INTEGER
{
$$ = (term *)smalloc(sizeof(term));
$$->coef = $1;
$$->xp = 0;
$$->yp = 0;
$$->zp = 0;
$$->nxt = (term *)NULL;
}
| NAME POWER LBRACE INTEGER RBRACE
{
char *p;
$$ = (term *)smalloc(sizeof(term));
$$->coef = 1;
$$->xp = 0;
$$->yp = 0;
$$->zp = 0;
$$->nxt = (term *)NULL;
for (p = $1; *p != 0; p++)
switch (*p) {
case 'x':
$$->xp += 1;
break;
case 'y':
$$->yp += 1;
break;
case 'z':
$$->zp += 1;
break;
default:
fatal("art: illegal name in equation.\n");
}
p--;
switch (*p) {
case 'x':
$$->xp += $4 - 1;
break;
case 'y':
$$->yp += $4 - 1;
break;
case 'z':
$$->zp += $4 - 1;
break;
default:
fatal("art: illegal name in equation.\n");
}
}
;
expr : FLOAT
{
$$ = (expression *)smalloc(sizeof(expression));
$$->type = EXP_FLOAT;
$$->u.f = $1;
}
| INTEGER
{
$$ = (expression *)smalloc(sizeof(expression));
$$->type = EXP_INT;
$$->u.i = $1;
}
| QUOTE NAME QUOTE
{
$$ = (expression *)smalloc(sizeof(expression));
$$->type = EXP_INT;
$$->u.i = *$2;
free($2);
}
| NAME
{
$$ = get_varexpr($1);
}
| expr PLUS expr
{
$$ = get_expr(EXP_ADD, $1, $3);
}
| expr MINUS expr
{
$$ = get_expr(EXP_SUB, $1, $3);
}
| expr MULT expr
{
$$ = get_expr(EXP_MUL, $1, $3);
}
| expr DIV expr
{
$$ = get_expr(EXP_DIV, $1, $3);
}
| MINUS expr %prec UMINUS
{
$$ = get_expr(EXP_UMINUS, $2, (expression *)NULL);
}
;